package com.cgnpc.scp.hse.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.cgnpc.cud.core.domain.AjaxResult;
import com.cgnpc.scp.common.exception.ScpException;
import com.cgnpc.scp.common.pojo.UserInfo;
import com.cgnpc.scp.common.utils.AjaxResultUtil;
import com.cgnpc.scp.common.utils.ListUtil;
import com.cgnpc.scp.common.utils.StringUtil;
import com.cgnpc.scp.hse.mybatis.entity.HseCheckOptionsConfig;
import com.cgnpc.scp.hse.mybatis.entity.HseCheckOptionsConfigExampleExtend;
import com.cgnpc.scp.hse.mybatis.mapper.client.HseCheckOptionsConfigMapper;
import com.cgnpc.scp.hse.service.IHseCheckOptionsConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;

@Service
public class HseCheckOptionsConfigServiceImpl implements IHseCheckOptionsConfigService {
    private static final Logger LOGGER = LoggerFactory.getLogger(HseCheckOptionsConfigServiceImpl.class);

    @Autowired
    private MessageSource messageSource;

    @Autowired
    private HseCheckOptionsConfigMapper hseCheckOptionsConfigMapper;

    @Override
    public <T extends HseCheckOptionsConfig> List<T> queryByMeetingInfoId(String meetingInfoId) {
        if (StringUtil.isNullOrSpace(meetingInfoId)) {
            return null;
        }

        QueryWrapper<HseCheckOptionsConfig> queryWrapper = new QueryWrapper<>();

        queryWrapper.orderByAsc("order_index");

        queryWrapper.eq("meeting_info_id", meetingInfoId);

        return (List<T>) hseCheckOptionsConfigMapper.selectList(queryWrapper);
    }

    @Override
    public <T extends HseCheckOptionsConfig> List<T> queryTreeByMeetingInfoId(String meetingInfoId) {
        List<T> resultConfigList = new ArrayList<>();
        List<T> dbHseCheckOptionsConfigList = this.queryByMeetingInfoId(meetingInfoId);

        if (ListUtil.getListSizeWith0(dbHseCheckOptionsConfigList) > 0) {
            resultConfigList.addAll(dbHseCheckOptionsConfigList);

            Map<String, T> hseConfigIdWithConfigObjectMap = new HashMap<>();

            for (T dbHseCheckOptionsConfig : dbHseCheckOptionsConfigList) {
                hseConfigIdWithConfigObjectMap.put(dbHseCheckOptionsConfig.getId(), dbHseCheckOptionsConfig);
            }

            T hseConfigIdWithConfigObjectParent = null;

            for (T dbHseCheckOptionsConfig : dbHseCheckOptionsConfigList) {
                hseConfigIdWithConfigObjectParent = hseConfigIdWithConfigObjectMap.get(dbHseCheckOptionsConfig.getParentId());

                if (hseConfigIdWithConfigObjectParent != null) {
                    if (hseConfigIdWithConfigObjectParent.getChildren() == null) {
                        hseConfigIdWithConfigObjectParent.setChildren(new ArrayList<>());
                    }

                    hseConfigIdWithConfigObjectParent.getChildren().add(dbHseCheckOptionsConfig);
                    resultConfigList.remove(dbHseCheckOptionsConfig);
                }
            }
        }

        return resultConfigList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public <T extends HseCheckOptionsConfig> int save(UserInfo loginUserInfo, Locale reqLocale, String meetingInfoId, List<T> reqEntityList) {
        int saveRows = 0;

        try {
            if (ListUtil.getListSizeWith0(reqEntityList) <= 0) {
                return 0;
            }

            for (T reqEntity : reqEntityList) {
                saveRows += hseCheckOptionsConfigMapper.insert(reqEntity);
            }

        } catch (Exception e) {
            LOGGER.error("save.error;", e);
            throw e;
        }

        return saveRows;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public <T extends HseCheckOptionsConfig> AjaxResult inspection(UserInfo loginUserInfo, Locale reqLocale, List<T> reqEntityList) {
        final String logInfo = "[inspection_UUID_" + UUID.randomUUID().toString() + "]";
        AjaxResult ajaxResult = null;

        try {
            final int reqEntityListSize = ListUtil.getListSizeWith0(reqEntityList);

            if (reqEntityListSize <= 0) {
                LOGGER.error("{}reqEntityListSize <= 0;", logInfo);
                return AjaxResultUtil.createI18nErrorDefaultMessage(reqLocale, messageSource);
            }

            Date nowDate = new Date();
            // begin 获取登录用户的信息
            String loginUserInfoUserId = loginUserInfo.getUserId();
            String loginUserInfoUserName = loginUserInfo.getUserName();
            // end 获取登录用户的信息

            // begin 校验请求数据
            List<String> reqMeetingInfoIdList = new ArrayList<>();
            List<String> reqOptionIdList = new ArrayList<>();
            Map<String, HseCheckOptionsConfig> reqOptionIdWithOptionMap = new HashMap<>();

            String reqMeetingInfoId = null;
            String reqId = null;
            // String reqOptionText = null;

            for (T reqEntity : reqEntityList) {
                reqMeetingInfoId = reqEntity.getMeetingInfoId();
                reqId = reqEntity.getId();
                // reqOptionText = reqEntity.getOptionText();

                if (StringUtil.isNullOrSpace(reqMeetingInfoId)) {
                    LOGGER.error("{}reqMeetingInfoId is null or space;", logInfo);
                    return AjaxResultUtil.createI18nErrorDefaultMessage(reqLocale, messageSource);
                }

                if (StringUtil.isNullOrSpace(reqId)) {
                    LOGGER.error("{}reqId is null or space;", logInfo);
                    return AjaxResultUtil.createI18nErrorDefaultMessage(reqLocale, messageSource);
                }

                if (!reqMeetingInfoIdList.contains(reqMeetingInfoId)) {
                    reqMeetingInfoIdList.add(reqMeetingInfoId);
                }

                if (!reqOptionIdList.contains(reqId)) {
                    reqOptionIdList.add(reqId);
                }

                reqOptionIdWithOptionMap.put(reqId, reqEntity);
            }

            if (ListUtil.getListSizeWith0(reqMeetingInfoIdList) != 1) {
                LOGGER.error("{}请求的会议id不为1个；reqMeetingInfoIdList:{};", logInfo, reqMeetingInfoIdList);
                return AjaxResultUtil.createErrorMessage("请求数据不正确");
            }

            final String usedReqMeetingInfoId = reqMeetingInfoIdList.get(0);
            // end 校验请求数据

            // begin 对比请求数据和数据库数据
            final List<Integer> usedNeedInspectionList = Arrays.asList(HseCheckOptionsConfig.NEEDINSPECTION_1, HseCheckOptionsConfig.NEEDINSPECTION_2);

            QueryWrapper<HseCheckOptionsConfig> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("meeting_info_id", usedReqMeetingInfoId);
            queryWrapper.in("id", reqOptionIdList);
            queryWrapper.in("need_inspection", usedNeedInspectionList);

            List<HseCheckOptionsConfig> dbHseCheckOptionsConfigList = hseCheckOptionsConfigMapper.selectList(queryWrapper);
            int dbHseCheckOptionsConfigListSize = ListUtil.getListSizeWith0(dbHseCheckOptionsConfigList);

            if (dbHseCheckOptionsConfigListSize <= 0) {
                LOGGER.error("{}dbHseCheckOptionsConfigListSize <= 0;数据库没有检查配置项相关信息；请求数据不正确；", logInfo);
                return AjaxResultUtil.createErrorMessage("请求数据不正确");
            }

            if (dbHseCheckOptionsConfigListSize != reqEntityListSize) {
                LOGGER.error("{}dbHseCheckOptionsConfigListSize != reqEntityListSize；"
                                + "dbHseCheckOptionsConfigListSize:{};reqEntityListSize:{};"
                        , logInfo
                        , dbHseCheckOptionsConfigListSize, reqEntityListSize
                );
                return AjaxResultUtil.createErrorMessage("请求数据不正确");
            }
            // end 对比请求数据和数据库数据

            // begin 解析并获取父节点对应的子节点集合
            Map<String, List<HseCheckOptionsConfig>> dbOptionParentIdWithChildrenOptionMap = new HashMap<>();
            // Map<String, List<String>> dbOptionParentIdWithChildrenOptionIdMap = new HashMap<>();
            String dbOptionParentId = null;
            String dbOptionId = null;

            for (HseCheckOptionsConfig dbHseCheckOptionsConfig : dbHseCheckOptionsConfigList) {
                dbOptionParentId = dbHseCheckOptionsConfig.getParentId();
                // dbOptionId = dbHseCheckOptionsConfig.getId();

                if (!dbOptionParentIdWithChildrenOptionMap.containsKey(dbOptionParentId)) {
                    dbOptionParentIdWithChildrenOptionMap.put(dbOptionParentId, new ArrayList<>());
                    // dbOptionParentIdWithChildrenOptionIdMap.put(dbOptionParentId, new ArrayList<>());
                }

                dbOptionParentIdWithChildrenOptionMap.get(dbOptionParentId).add(dbHseCheckOptionsConfig);
                // dbOptionParentIdWithChildrenOptionIdMap.get(dbOptionParentId).add(dbOptionId);
            }
            // end 解析并获取父节点对应的子节点集合

            // begin 解析数据库的数据并重新设置值
            Iterator<Map.Entry<String, List<HseCheckOptionsConfig>>> itDbOptionParentIdWithChildrenOption = dbOptionParentIdWithChildrenOptionMap.entrySet().iterator();
            Map.Entry<String, List<HseCheckOptionsConfig>> entryDbOptionParentIdWithChildrenOption = null;
            String mapKeyWithDbOptionParentId = null;
            List<HseCheckOptionsConfig> mapValueWithDbChildrenOptionList = null;
            Integer dbOptionNeedInspection = null;
            String usedOptionText = null;
            String usedOptionTextEn = null;

            while (itDbOptionParentIdWithChildrenOption.hasNext()) {
                entryDbOptionParentIdWithChildrenOption = itDbOptionParentIdWithChildrenOption.next();
                mapKeyWithDbOptionParentId = entryDbOptionParentIdWithChildrenOption.getKey();
                mapValueWithDbChildrenOptionList = entryDbOptionParentIdWithChildrenOption.getValue();

                // begin 将同一个父id下的检查项重置为未检查状态N
//                HseCheckOptionsConfig updateNullConfig = new HseCheckOptionsConfig();
//                updateNullConfig.setIsInspection(HseCheckOptionsConfig.ISINSPECTION_N);
//                updateNullConfig.setInspectionTime(null); // null值不好设置
//                updateNullConfig.setInspectionUser("");
//                updateNullConfig.setInspectionUserName("");
//                updateNullConfig.setLastUpdateTime(nowDate);
//                updateNullConfig.setLastUpdateUser(loginUserInfoUserId);
//                updateNullConfig.setLastUpdateUserName(loginUserInfoUserName);
//
//                UpdateWrapper<HseCheckOptionsConfig> updateNullWrapper = new UpdateWrapper<>();
//                updateNullWrapper.eq("meeting_info_id", usedReqMeetingInfoId);
//                updateNullWrapper.in("need_inspection", usedNeedInspectionList);
//                updateNullWrapper.eq("parent_id", mapKeyWithDbOptionParentId);
//
//                hseCheckOptionsConfigMapper.update(updateNullConfig, updateNullWrapper);

                HseCheckOptionsConfigExampleExtend updateNullOptionConfig = new HseCheckOptionsConfigExampleExtend();
                updateNullOptionConfig.setIsInspection(HseCheckOptionsConfig.ISINSPECTION_N);
                updateNullOptionConfig.setInspectionTimeSetNull(true);
                updateNullOptionConfig.setInspectionUserSetNull(true);
                updateNullOptionConfig.setInspectionUserNameSetNull(true);
                updateNullOptionConfig.setLastUpdateTime(nowDate);
                updateNullOptionConfig.setLastUpdateUser(loginUserInfoUserId);
                updateNullOptionConfig.setLastUpdateUserName(loginUserInfoUserName);

                updateNullOptionConfig.setMeetingInfoIdEqualTo(usedReqMeetingInfoId);
                updateNullOptionConfig.setNeedInspectionIn(usedNeedInspectionList);
                updateNullOptionConfig.setParentIdEqualTo(mapKeyWithDbOptionParentId);

                hseCheckOptionsConfigMapper.updateInspection(updateNullOptionConfig);
                // end 将同一个父id下的检查项重置为未检查状态N

                for (HseCheckOptionsConfig dbOption : mapValueWithDbChildrenOptionList) {
                    dbOptionId = dbOption.getId();
                    dbOptionNeedInspection = dbOption.getNeedInspection();

                    usedOptionText = null;
                    usedOptionTextEn = null;

                    if (dbOptionNeedInspection == HseCheckOptionsConfig.NEEDINSPECTION_1) {
                        // 检查类型1为选择类型，不需要更新optionText值
                    }

                    if (dbOptionNeedInspection == HseCheckOptionsConfig.NEEDINSPECTION_2) {
                        HseCheckOptionsConfig reqOption = reqOptionIdWithOptionMap.get(dbOptionId);
                        usedOptionText = reqOption.getOptionText();
                        usedOptionTextEn = reqOption.getOptionTextEn();
                    }

                    // begin 将指定的检查项改成已检查
                    HseCheckOptionsConfig usedUpdateConfig = new HseCheckOptionsConfig();
                    usedUpdateConfig.setIsInspection(HseCheckOptionsConfig.ISINSPECTION_Y);
                    usedUpdateConfig.setInspectionTime(nowDate);
                    usedUpdateConfig.setInspectionUser(loginUserInfoUserId);
                    usedUpdateConfig.setInspectionUserName(loginUserInfoUserName);
                    usedUpdateConfig.setOptionText(usedOptionText);
                    usedUpdateConfig.setOptionTextEn(usedOptionTextEn);
                    usedUpdateConfig.setLastUpdateTime(nowDate);
                    usedUpdateConfig.setLastUpdateUser(loginUserInfoUserId);
                    usedUpdateConfig.setLastUpdateUserName(loginUserInfoUserName);

                    UpdateWrapper<HseCheckOptionsConfig> updateWrapper = new UpdateWrapper();
                    updateWrapper.eq("meeting_info_id", usedReqMeetingInfoId);
                    updateWrapper.in("need_inspection", usedNeedInspectionList);
                    updateWrapper.eq("id", dbOptionId);

                    int hseConfigUpdateRows = hseCheckOptionsConfigMapper.update(usedUpdateConfig, updateWrapper);

                    if (hseConfigUpdateRows != 1) {
                        LOGGER.error("{}hseConfigUpdateRows != 1;hseConfigUpdateRows:{};", logInfo, hseConfigUpdateRows);
                        throw new ScpException("检查失败");
                    }
                    // end 将指定的检查项改成已检查
                }
            }
            // end 解析数据库的数据并重新设置值

            ajaxResult = AjaxResultUtil.createI18nSuccessDefaultMessage(reqLocale, messageSource);
        } catch (Exception e) {
            LOGGER.error("{}inspection.error;", logInfo, e);
            throw e;
        }

        return ajaxResult;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public <T extends HseCheckOptionsConfig> AjaxResult deleteById(List<String> reqMeetingInfoIdList) {
        AjaxResult ajaxResult = null;
        final String logInfo = "[HseCheckOptionsConfig_deleteById_UUID_" + UUID.randomUUID().toString() + "]";

        try {
            if (ListUtil.getListSizeWith0(reqMeetingInfoIdList) <= 0) {
                return AjaxResultUtil.createSuccessMessage("操作成功");
            }

            LOGGER.info("{}printInfo;reqMeetingInfoIdList:{};"
                    , logInfo
                    , reqMeetingInfoIdList
            );

            UpdateWrapper<HseCheckOptionsConfig> updateWrapper = new UpdateWrapper<>();

            updateWrapper.in("meeting_info_id", reqMeetingInfoIdList);

            int hseCheckOptionsConfigDelRows = hseCheckOptionsConfigMapper.delete(updateWrapper);
            LOGGER.info("{}hseCheckOptionsConfigDelRows:{};"
                    , logInfo
                    , hseCheckOptionsConfigDelRows
            );

            ajaxResult = AjaxResultUtil.createSuccessMessage("删除成功");
        } catch (Exception e) {
            LOGGER.error("{}inspection.error;", logInfo, e);
            throw e;
        }

        return ajaxResult;
    }
}
